package com.photoeditor.demo.model.image;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;

import com.photoeditor.R;
import com.photoeditor.demo.model.image.util.ImageHelper;
import com.photoeditor.demo.model.bean.BitmapBean;
import com.photoeditor.demo.ui.widget.image.BitmapImageView;
import com.photoeditor.demo.ui.activity.edit.ImagePreviewActivity;
import com.photoeditor.demo.ui.widget.image.PlayImageView;
import com.photoeditor.demo.ui.widget.image.VideoImageView;
import com.photoeditor.demo.util.BitmapDecoder;
import com.photoeditor.demo.util.FetcherHolder;
import com.photoeditor.demo.util.ILoadBitmap;
import com.photoeditor.demo.util.MediaTypeUtil;

import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 只用于加载视频 和 一些特殊的图片（不包含PNG和JPG和GIF）
 */
public class ImageLoaderInterface
{

	/**
	 * 图片缓存的核心对象
	 */
	protected LruCache<Uri, Bitmap> mLruCache;
	
	protected Object mLruCacheLockObject = new Object();
	/**
	 * 线程池
	 */
	protected ExecutorService mThreadPool;
	
	protected Object mThreadPoolLockObject = new Object();
	/**
	 * UI线程中的Handler
	 */
	protected UIHandler mUIHandler;
	
	/**
	 * 用于存储需要执行的Runnable
	 */
	protected LinkedHashMap<Uri, Runnable> mRunnables;
	
	protected int RUNNABLE_SIZE = 4;
	
	protected Object mRunnableLockObject = new Object();
	
	protected boolean isLru = true;
	
	protected int THREAD_POOL_SIZE = 4;
	
	public final int REFRESH_ENABLE = 100;
	public final int REFRESH_DISABLE = 101;
	public final int REFRESH_DISPLAY = 102;
	
	private final static int CACHE_MEMORY = 10 * 1024 * 1024; // 20M
	
	public ImageLoaderInterface()
	{
		init();
	}
	
	/**
	 * 初始化
	 */
	protected void init()
	{
//		// 获取我们应用的最大可用内存
//		int maxMemory = (int) Runtime.getRuntime().maxMemory();
//		int cacheMemory = maxMemory/6;
		mLruCache = new LruCache<Uri, Bitmap>(CACHE_MEMORY)
		{
			@SuppressLint("NewApi")
			@Override
			protected int sizeOf(Uri key, Bitmap value)
			{
				return value.getRowBytes() * value.getHeight();
			}
			
			@Override
			protected void entryRemoved(boolean evicted, Uri key,
					Bitmap oldValue, Bitmap newValue) {
				super.entryRemoved(evicted, key, oldValue, newValue);
			}
		};
		
		mRunnables = new LinkedHashMap<Uri, Runnable>(RUNNABLE_SIZE, 1, isLru){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public Runnable put(Uri key, Runnable value) {
				Runnable value2 = mRunnables.get(key);
				if(value2 != null && value2 instanceof RunnableA){
					return super.put(key, value2);
				}
				return super.put(key, value);
			}
			@Override
			protected boolean removeEldestEntry(
					Entry<Uri, Runnable> eldest) {
				synchronized (mRunnableLockObject) {
					if(size() > RUNNABLE_SIZE){
						return true;
					}
					return super.removeEldestEntry(eldest);
				}
			}
		};

		// 创建线程池
		mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

		mUIHandler = new UIHandler(Looper.getMainLooper());
	}

	public void removeSameRunnable(Uri key){
		try {
			synchronized (mRunnableLockObject) {
				mRunnables.remove(key);
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	/**
	 * 特殊方法直接在线程池中进行加载
	 * @param bean
	 * @param v
	 * @param uriErr
	 */
	public void runInThreadPool(final BitmapBean bean, final View v, final ILoadBitmap uriErr){

		v.setTag(bean.mUri);
		// 根据path在缓存中获取bitmap
		Bitmap bm = getBitmapFromLruCache(bean.mUri);

		if (bm != null)
		{
			mUIHandler.refreashBitmap(bean, v, bm, REFRESH_ENABLE);
		} else{
			synchronized(mThreadPoolLockObject){
				if(!mThreadPool.isShutdown()){
					mThreadPool.execute(buildTask(bean, v, uriErr));
				}
			}
		}
	}

	public void startTimerTask(){

	}

	protected Runnable getNewestRunnable(){
		synchronized(mRunnableLockObject){
			Set<Uri> set = mRunnables.keySet();
			int size = set.size();
			if(size == 0) return null;
			int i = 0;
			for(Uri u : set){
				i++;
				if(i == size){
					return mRunnables.remove(u);
				}
			}
			return null;
		}
	}

	/**
	 * 根据传入的参数，新建一个任务
	 * @param bean
	 * @param v
	 * @param uriErr
	 * @return
	 */
	protected RunnableA buildTask(BitmapBean bean, View v , ILoadBitmap uriErr)
	{
		return new RunnableA(bean, v, uriErr);
	}
	/**
	 * 根据传入的参数，新建一个任务
	 * @param bean
	 * @param uriErr
	 * @return
	 */
	protected RunnableB buildTask(final BitmapBean bean, final ILoadBitmap uriErr)
	{
		return new RunnableB(bean, uriErr);
	}


	protected RunnableC buildTask(final String path)
	{
		return new RunnableC(path);
	}


	protected class RunnableA implements Runnable{
		public BitmapBean mBean;
		ILoadBitmap mUriErr;
		View mView;
		public RunnableA(BitmapBean bean, View v, ILoadBitmap uriErr){
			mBean = bean;
			mUriErr = uriErr;
			mView = v;
		}
		@Override
		public void run() {
			Bitmap bm = null;
			if(MediaTypeUtil.isImage(mBean.mType)){//Image
				bm = ImageHelper.UriToBitmap(mBean, mUriErr, mUIHandler, mView);
			}else{//Video
				bm = ImageHelper.videoToBitmap(mBean);
			}
			if(bm == null){
				mUIHandler.refreashBitmap(mBean, mView, null, REFRESH_DISABLE);
				if(mUriErr != null){
					mUriErr.OnUriError(mBean);
				}
			}else{
				// 3、把图片加入到缓存
				addBitmapToLruCache(mBean.mUri, bm);
				mUIHandler.refreashBitmap(mBean, mView, bm, REFRESH_ENABLE);
			}
		}
	}
	protected class RunnableB implements Runnable{
		public BitmapBean mBean;
		ILoadBitmap mUriErr;
		public RunnableB(BitmapBean bean, ILoadBitmap uriErr){
			mBean = bean;
			mUriErr = uriErr;
		}
		@Override
		public void run() {
			Bitmap bm = null;
			if(MediaTypeUtil.isImage(mBean.mType)){//Image
				bm = ImageHelper.UriToBitmap(mBean, mUriErr, null, null);
			}else{//video
				bm = ImageHelper.videoToBitmap(mBean);
			}
			if(bm == null){
				if(mUriErr != null){
					mUriErr.OnUriError(mBean);
				}
			}else{
				// 3、把图片加入到缓存
				addBitmapToLruCache(mBean.mUri, bm);
			}
		}
	}

	protected class RunnableC implements Runnable{
		public String path;
		public RunnableC(String str){
			path = str;
		}
		@Override
		public void run() {
			BitmapRegionDecoder decoder = null;
			try {
				if(BitmapDecoder.isVaildImage(path)) {
					decoder = BitmapRegionDecoder.newInstance(path, false);
				}
				FetcherHolder.getPreviewBitmapCache().addDecoderToCache(path, decoder);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}


	/**
	 * 将图片加入LruCache
	 *
	 * @param uri
	 * @param bm
	 */
	protected void addBitmapToLruCache(Uri uri, Bitmap bm)
	{

		synchronized(mLruCacheLockObject){
			if(mLruCache != null){
				if (getBitmapFromLruCache(uri) == null)
				{
					if (uri != null && bm != null){
						mLruCache.put(uri, bm);
					}
				}
			}
		}
	}

	/**
	 * 根据Uri在缓存中获取bitmap
	 *
	 * @param key
	 * @return
	 */
	public Bitmap getBitmapFromLruCache(Uri key)
	{
		synchronized (mLruCacheLockObject) {
			if(mLruCache == null) return null;
			return mLruCache.get(key);
		}
	}


	protected class ImgBeanHolder
	{
		Bitmap bitmap;
		View view;
		BitmapBean bean;
	}


	public class UIHandler extends Handler{

		public UIHandler(Looper lp){
			super(lp);
		}

		@Override
		public void handleMessage(Message msg) {
			if(msg.what == REFRESH_ENABLE){
				// 获取得到图片，为imageview回调设置图片
				ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
				Bitmap bm = holder.bitmap;
				View v = holder.view;
				Uri path = holder.bean.mUri;

				int bw = bm.getWidth();
				int bh = bm.getHeight();
				float dp = 1.0f;

				int nbw = 0;
				int nbh = 0;
				// 将path与getTag存储路径进行比较
				if (v.getTag().equals(path))
				{
					if(v instanceof BitmapImageView){
						final BitmapImageView view = ((BitmapImageView) v);
						if(holder.bean.mDegree == 90 || holder.bean.mDegree == 270){
							if(bw * 1.0f / bh >= ImagePreviewActivity.SCREEN_WIDTH * 1.0f / ImagePreviewActivity.SCREEN_HEIGHT){//当前是顶着宽
								nbw = ImagePreviewActivity.SCREEN_WIDTH;
								nbh = (int)(nbw * 1.0f / bw * bh + 0.5f);
								int temp = nbw;
								nbw = nbh;
								nbh = temp;
								if(nbw * 1.0f / nbh >= ImagePreviewActivity.SCREEN_WIDTH * 1.0f / ImagePreviewActivity.SCREEN_HEIGHT){//顶着宽
									dp = ImagePreviewActivity.SCREEN_WIDTH * 1.0f / nbw;
								} else{//顶着高
									dp = ImagePreviewActivity.SCREEN_HEIGHT * 1.0f / nbh;
								}
							} else{//当前是顶着高
								nbh = ImagePreviewActivity.SCREEN_HEIGHT;
								nbw = (int)(nbh * 1.0f / bh * bw + 0.5f);
								int temp = nbw;
								nbw = nbh;
								nbh = temp;
								if(nbw * 1.0f / nbh >= ImagePreviewActivity.SCREEN_WIDTH * 1.0f / ImagePreviewActivity.SCREEN_HEIGHT){//顶着宽
									dp = ImagePreviewActivity.SCREEN_WIDTH * 1.0f / nbw;
								} else{//顶着高
									dp = ImagePreviewActivity.SCREEN_HEIGHT * 1.0f / nbh;
								}
							}
						}
						view.setDisplayViewGone();
						view.getImageView().setImageBitmap(bm);
						if(holder.bean.mDegree != 0){
							int w = view.getImageView().getWidth();
							int h = view.getImageView().getHeight();
							Matrix m = view.getImageView().getImageMatrix();
							if(m != null){
								m.postRotate(holder.bean.mDegree, w / 2, h / 2);
								if(dp != 1){
									m.postScale(dp, dp, w / 2, h / 2);
								}
							}
							view.getImageView().setImageMatrix(m);

							Matrix m1 = new Matrix();
							m1.postRotate(holder.bean.mDegree, w / 2, h / 2);
							if(dp != 1){
								m1.postScale(dp, dp, w / 2, h / 2);
							}
							view.getImageView().setDisplayMatrix(m1);
							view.getImageView().setMinimumScale(dp);
						}

					} else if(v instanceof VideoImageView){
						VideoImageView  view = ((VideoImageView) v);
						if(holder.bean.mDegree == 90 || holder.bean.mDegree == 270){
							int temp = bw;
							bw = bh;
							bh  = temp;
							if(bw * 1.0f / bh >= ImagePreviewActivity.SCREEN_WIDTH * 1.0f / ImagePreviewActivity.SCREEN_HEIGHT){//顶着宽
								if(bw > bh){//原来是顶着宽
									dp = 1.0f;
								} else{//原来是顶着高的
									nbh = ImagePreviewActivity.SCREEN_WIDTH;
									nbw = (int)(nbh * 1.0f / bh * bw);
									dp = ImagePreviewActivity.SCREEN_WIDTH * 1.0f / nbw;
								}
							} else{//顶着高
								if(bw < bh){//原来是顶着高的
									nbh = ImagePreviewActivity.SCREEN_WIDTH;
									nbw = (int)(nbh * 1.0f / bh * bw);
									dp = ImagePreviewActivity.SCREEN_HEIGHT * 1.0f / nbh;
								} else{//原来是顶着宽
									dp = 1.0f;
								}
							}
						}
						view.setDisplayViewGone();
						view.getVideoImageView().setImageBitmap(bm);
						view.getVideoImageView().setRotation(holder.bean.mDegree);
						view.getVideoImageView().setScaleX(dp);
						view.getVideoImageView().setScaleY(dp);
					} else if(v instanceof PlayImageView){
						PlayImageView  view = ((PlayImageView) v);
						ViewGroup.LayoutParams params = view.getDisplayView().getLayoutParams();
						params.width = ViewGroup.LayoutParams.MATCH_PARENT;
						params.height = ViewGroup.LayoutParams.MATCH_PARENT;
						view.getDisplayView().setLayoutParams(params);
						view.getDisplayView().setBackgroundColor(Color.BLACK);
						view.getDisplayView().setScaleType(ImageView.ScaleType.FIT_CENTER);
						view.getDisplayView().setImageBitmap(bm);
					}

				}
			} else if(msg.what == REFRESH_DISABLE){
				ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
				View v = holder.view;
				Uri path = holder.bean.mUri;
				if (v.getTag().equals(path)){
					if(v instanceof BitmapImageView){

						BitmapImageView view = ((BitmapImageView) v);
						TextView tv = new TextView(v.getContext());
						tv.setText(R.string.image_broken);
						tv.setTextColor(0x7fffffff);
						LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
						lp.addRule(RelativeLayout.BELOW, R.id.display_view);
						lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
						lp.topMargin = v.getContext().getResources().getDimensionPixelSize(R.dimen.load_error_margin_top);
						view.getDisplayLayout().addView(tv, lp);

						ImageView dv = view.getDisplayView();
						LayoutParams dlp = (LayoutParams)dv.getLayoutParams();
						dlp.width = LayoutParams.WRAP_CONTENT;
						dlp.height = LayoutParams.WRAP_CONTENT;
						dv.setLayoutParams(dlp);
						dv.setBackgroundDrawable(null);
						dv.setImageResource(R.drawable.ic_load_image_broken);
						view.getImageView().setImageResource(R.color.transpant);

						view.setDisplayLayoutPaddingBottom(R.dimen.load_error_move);
					} else if(v instanceof VideoImageView){

						VideoImageView  view = ((VideoImageView) v);
						TextView tv = new TextView(v.getContext());
						tv.setText(R.string.video_broken);
						tv.setTextColor(0x7fffffff);
						LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
						lp.addRule(RelativeLayout.BELOW, R.id.display_view);
						lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
						lp.topMargin = v.getContext().getResources().getDimensionPixelSize(R.dimen.load_error_margin_top);
						view.getDisplayLayout().addView(tv, lp);

						ImageView dv = view.getDisplayView();
						LayoutParams dlp = (LayoutParams)dv.getLayoutParams();
						dlp.width = LayoutParams.WRAP_CONTENT;
						dlp.height = LayoutParams.WRAP_CONTENT;
						dv.setLayoutParams(dlp);
						dv.setBackgroundDrawable(null);
						dv.setImageResource(R.drawable.ic_load_image_broken);
						view.getVideoImageView().setImageResource(R.color.transpant);

						view.setDisplayLayoutPaddingBottom(R.dimen.load_error_move);
						view.setPlayViewGone();
					}
				}
			} else if(msg.what == REFRESH_DISPLAY){
				ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
				View v = holder.view;
				BitmapBean bean = holder.bean;
				if (v.getTag().equals(bean.mUri)){
					if(v instanceof BitmapImageView){
						BitmapImageView view = ((BitmapImageView) v);
						if(bean.mHeight != -1 && bean.mHeight != 0){
							int a[] = ImageHelper.getKnownBitmapSize(bean, ImagePreviewActivity.SCREEN_WIDTH,
									ImagePreviewActivity.SCREEN_HEIGHT);
							ImageView iv = view.getDisplayView();
							LayoutParams rlp = (LayoutParams)iv.getLayoutParams();
							rlp.height = a[1];
							rlp.width = a[0];
							iv.setLayoutParams(rlp);
							iv.setBackgroundResource(R.color.image_background);
							iv.setImageResource(R.drawable.ic_default_image);
						}
					}
				}
			}
		}
		
		/**
		 * 刷新显示
		 * @param bean
		 * @param v
		 * @param bm
		 * @param msg
		 */
		public void refreashBitmap(final BitmapBean bean, final View v,
				Bitmap bm, int msg){
			Message message = Message.obtain(this, msg);
			ImgBeanHolder holder = new ImgBeanHolder();
			holder.bitmap = bm;
			holder.bean = bean;
			holder.view = v;
			message.obj = holder;
			this.sendMessage(message);
		}
		
		public void refreashDiaplay(final BitmapBean bean, final View v){
			Message message = Message.obtain(this, REFRESH_DISPLAY);
			ImgBeanHolder holder = new ImgBeanHolder();
			holder.bean = bean;
			holder.view = v;
			message.obj = holder;
			this.sendMessage(message);
		}
	}
	
	public void onDestory(){
		try {
			synchronized(mLruCacheLockObject){
				Set<Uri> set = mLruCache.snapshot().keySet();
				for(Uri u : set){
					if(u != null){
						Bitmap bitmap = mLruCache.remove(u);
						if(bitmap != null && !bitmap.isRecycled()){
							bitmap.recycle();
						}
					}
				}
				mLruCache.evictAll();
				mLruCache = null;
			}
			synchronized (mThreadPoolLockObject) {
				mThreadPool.shutdownNow();
			}
			synchronized (mRunnableLockObject) {
				mRunnables.clear();
			}
			System.gc();
			mUIHandler.removeCallbacksAndMessages(null);
		} catch (Throwable e) {
			System.gc();
		}
	}

	/**
	 * 加载图片 会先放入LinkedHashMap中然后才开始加载并设置到ImageView上
	 * @param bean
	 * @param v
	 * @param uriErr
	 */
	public void loadImage(final BitmapBean bean, final View v, final ILoadBitmap uriErr) {}

	/**
	 * 加载图片 会先放入LinkedHashMap中然后才开始加载
	 * @param bean
	 * @param uriErr
	 */
	public void loadImage(final BitmapBean bean, final ILoadBitmap uriErr) {}

	public void loadDecoder(final BitmapBean bean) {}

}
